

#include "shell.h"
#include "memory.h"
#include "string.h"
#include "thread.h"

struct task_struct* shell_block_task;
struct task_struct* cur_thread;
uint32_t* guest_video_memory_cache;
void my_shell(void* arg)
{
    cur_thread = running_thread();
    guest_video_memory_cache = get_kernel_pages(1);
    struct shell_buffer {
        unsigned char buffer[0x50];
        int head;
        int tail;
    };
    struct shell_buffer shell_buffer;
    shell_buffer.head = 0x0;
    shell_buffer.tail = 0x0;

    while(1) {
        
        if (keyboard_buffer.head == keyboard_buffer.tail) {
            thread_block(TASK_BLOCKED);
        } else {
            asm("cli");

            if (keyboard_buffer.tail == 0x100) {
                keyboard_buffer.tail = 0x0;
            }
            unsigned char char_code = keyboard_buffer.keyboard_buf[keyboard_buffer.tail];
            keyboard_buffer.tail++;

            if (!((char_code == 0x08) || (char_code == 0x0d))) {
                shell_buffer.buffer[shell_buffer.head] = char_code;
                shell_buffer.head++;
            }
            
            
            switch (char_code) {
                case '\r':
                put_char(char_code);
                if (!memcmp(&(shell_buffer.buffer), "clear", 5)) {
                    cls_screen();
                    put_str(">>>");
                    memset(&(shell_buffer.buffer), 0x00, 100);
                } 
                else if (!memcmp(&(shell_buffer.buffer), "blockvm", 7)) {
                    shell_block_task =  find_thread_all_list("vm1");
                    list_remove(&(shell_block_task->general_tag));
                    // dispaly_guest_video(0);
                    put_str(">>>");
                    memset(&(shell_buffer.buffer), 0x00, 100);
                }
                else if (!memcmp(&(shell_buffer.buffer), "unblockvm", 9)) {
                    append_ThreadReadyList(shell_block_task);
                    shell_block_task = NULL;
                    // dispaly_guest_video(1);
                    put_str(">>>");
                    memset(&(shell_buffer.buffer), 0x00, 100);
                }
                else {
                   
                    put_str(">>>");
                }
                shell_buffer.head = 0x0;
                shell_buffer.tail = 0x0;
                break;

                case 0x08:
                if (shell_buffer.head > 0) {
                    put_char(char_code);
                    shell_buffer.head--;
                }
                break;

                default:
                put_char(char_code);
                
            
            }
            asm("sti");
            
        }
    }
    
}
void dispaly_guest_video(int state) {
    if (state) {
        memcpy((void*)(0xc00b9000), guest_video_memory_cache, 0x1000);
    } else {
        memcpy(guest_video_memory_cache, (void*)(0xc00b9000), 0x1000);
        int counter = 0;
        uint16_t* pointer = (uint16_t*)(0xc00b9000);
        while(counter < 2000) {
            pointer[counter] = 0x0720;
            counter++;
        }
    }
    // *(uint8_t*)(0xc00b9000) = 'b';
    // *(uint8_t*)(0xc00b9002) = 'l';
    // *(uint8_t*)(0xc00b9004) = 'o';
    // *(uint8_t*)(0xc00b9006) = 'c';
    // *(uint8_t*)(0xc00b9008) = 'k';
    // *(uint8_t*)(0xc00b900a) = 'v';
    // *(uint8_t*)(0xc00b900c) = 'm';

}
void cls_screen(void) {
    int counter = 0;
    uint16_t* pointer = (uint16_t*)(0xc00b8000);
    while(counter < 2000) {
        pointer[counter] = 0x0720;
        counter++;
    }
    put_cursor = 0x0;
    // outb((uint16_t)0x3d4, (uint8_t)0xe);
    // outb((uint16_t)0x3d5, (0 >> 8 ) & 0xff);
    // outb((uint16_t)0x3d4, (uint8_t)0xf);
    // outb((uint16_t)0x3d5, (0 & 0xff));
}

void shell_init(void)
{
    thread_start("shell", 20, my_shell, "shell");
}